<?php
class DataBufferedWriterD extends CApplicationComponent {
	public $mongoOptions = array ();
	public $cacheId = '';
	public $blockSize = 30; 
	public $flushTime = 30;
	protected $_mogoInstance = null;
	protected $_cache = null;
	protected $_sort = array ();
	protected $_conds = array ();
	private $_attrs = array ();
	public function asc($field) {
		$this->_sort [$field] = 1;
		return $this;
	}
	public function desc($field) {
		$this->_sort [$field] = - 1;
		return $this;
	}
	public function addL() {
		throw new Exception ( 'addL not implents yet' );
	/**
	 * $this->_conds.='(';
	 * return $this;
	 */
	}
	public function addR() {
		throw new Exception ( 'addR not implents yet' );
	/**
	 * $this->_conds.=')';
	 * return $this;
	 */
	}
	public function andCond() {
		throw new Exception ( 'andCond not implents yet' );
	/**
	 * $this->_conds.=' && ';
	 * return $this;
	 */
	}
	/**
	 *
	 * @param $attr 字段名       	
	 * @param $operator 操作符       	
	 * @param $value 值       	
	 */
	protected function operator($attr, $operator, $value) {
		if (! isset ( $this->_conds [$attr] )) {
			$this->_conds [$attr] = array ();
		}
		$this->_conds [$attr] [$operator] = $value;
		return $this;
	}
	
	public function orCond() {
		throw new Exception ( 'orCond not implents yet' );
	/**
	 * $this->_conds.=' || ';
	 * return $this;
	 */
	}
	public function gt($attr, $value) {
		return $this->operator ( $attr, '$gt', $value );
	/**
	 * if($this->_conds!=='' && $this->_conds!=='('){
	 * $s=mb_substr($this->_conds,-3,3,'utf-8');
	 * if(strpos($s,'&&')===false && strpos($s,'||')===false){
	 * $this->_conds.=' && ';
	 * }
	 * }
	 * $this->_conds .="this.{$f} > {$v}";
	 * return $this;
	 */
	}
	public function gte($attr, $value) {
		return $this->operator ( $attr, '$gte', $value );
	/**
	 * if($this->_conds!=='' && $this->_conds!=='('){
	 * $s=mb_substr($this->_conds,-3,3,'utf-8');
	 * if(strpos($s,'&&')===false && strpos($s,'||')===false){
	 * $this->_conds.=' && ';
	 * }
	 * }
	 * $this->_conds .="this.{$f} >= {$v}";
	 * return $this;
	 */
	}
	public function lt($attr, $value) {
		return $this->operator ( $attr, '$lt', $value );
	/**
	 * if($this->_conds!=='' && $this->_conds!=='('){
	 * $s=mb_substr($this->_conds,-3,3,'utf-8');
	 * if(strpos($s,'&&')===false && strpos($s,'||')===false){
	 * $this->_conds.=' && ';
	 * }
	 * }
	 * $this->_conds .="this.{$f} < {$v}";
	 * return $this;
	 */
	}
	public function lte($attr, $value) {
		return $this->operator ( $attr, '$lte', $value );
	/**
	 * if($this->_conds!=='' && $this->_conds!=='('){
	 * $s=mb_substr($this->_conds,-3,3,'utf-8');
	 * if(strpos($s,'&&')===false && strpos($s,'||')===false){
	 * $this->_conds.=' && ';
	 * }
	 * }
	 * $this->_conds .="this.{$f} <= {$v}";
	 * return $this;
	 */
	}
	public function eq($attr, $value) {
		return $this->attr ( $attr, $value );
	/**
	 * if($this->_conds!=='' && $this->_conds!=='('){
	 * $s=mb_substr($this->_conds,-3,3,'utf-8');
	 * if(strpos($s,'&&')===false && strpos($s,'||')===false){
	 * $this->_conds.=' && ';
	 * }
	 * }
	 * $this->_conds .="this.{$f} == '{$v}'";
	 * return $this;
	 */
	}
	public function ne($attr, $value) {
		return $this->operator ( $attr, '$ne', $value );
	/**
	 * if($this->_conds!=='' && $this->_conds!=='('){
	 * $s=mb_substr($this->_conds,-3,3,'utf-8');
	 * if(strpos($s,'&&')===false && strpos($s,'||')===false){
	 * $this->_conds.=' && ';
	 * }
	 * }
	 * $this->_conds .="this.{$f} != '{$v}'";
	 * return $this;
	 */
	}
	public function in($attr, array $value) {
		return $this->operator ( $attr, '$in', $value );
	/**
	 * if($this->_conds!=='' && $this->_conds!=='('){
	 * $s=mb_substr($this->_conds,-3,3,'utf-8');
	 * if(strpos($s,'&&')===false && strpos($s,'||')===false){
	 * $this->_conds.=' && ';
	 * }
	 * }
	 * $this->_conds=' (';
	 * foreach($v as $vv){
	 * $this->_conds .="this.{$f} == '{$vv}' || ";
	 * }
	 * $this->_conds=mb_substr($this->_conds,0,-3,'utf-8');
	 * $this->_conds.=' ) ';
	 * return $this;
	 */
	}
	public function nin($attr, array $value) {
		return $this->operator ( $attr, '$nin', $value );
	
		/**
	 * if($this->_conds!=='' && $this->_conds!=='('){
	 * $s=mb_substr($this->_conds,-3,3,'utf-8');
	 * if(strpos($s,'&&')===false && strpos($s,'||')===false){
	 * $this->_conds.=' && ';
	 * }
	 * }
	 * $this->_conds=' (';
	 * foreach($v as $vv){
	 * $this->_conds .="this.{$f} == '{$vv}' && ";
	 * }
	 * $this->_conds=mb_substr($this->_conds,0,-3);
	 * $this->_conds.=' ) ';
	 * return $this;
	 */
	}
	/**
	 * 指定属性值
	 *
	 * @param $nameOrAttrs string|array
	 *       	 属性名或一组属性值
	 * @param $value string
	 *       	 属性值
	 * @return RQuery
	 */
	public function attr($nameOrAttrs, $value = null) {
		if (! is_array ( $nameOrAttrs )) {
			$nameOrAttrs = array ($nameOrAttrs => $value );
		}
		foreach ( $nameOrAttrs as $attr => $value ) {
			if ($attr == "_id" && (! is_object ( $value ) || ! ($value instanceof MongoId)) && strlen ( $attr ) == 24) {
				$value = new MongoId ( $value );
			}
			if (! isset ( $this->_attrs [$attr] )) {
				$this->_attrs [$attr] = array ();
			}
			if (is_array ( $value )) {
				$this->_attrs [$attr] = array_merge ( $this->_attrs [$attr], $value );
			} else {
				$this->_attrs [$attr] [] = $value;
			}
		}
		return $this;
	}
	public function like($attr, $value) {
		return $this->attr ( $attr, new MongoRegex ( $value ) );
	/**
	 * if($this->_conds!=='' && $this->_conds!=='('){
	 * $s=mb_substr($this->_conds,-3,3,'utf-8');
	 * if(strpos($s,'&&')===false && strpos($s,'||')===false){
	 * $this->_conds.=' && ';
	 * }
	 * }
	 * $this->_conds .="this.{$f}.test(/^$v/)";
	 * return $this;
	 */
	}
	/**
	 * 现有查询条件的组合
	 *
	 * @return array
	 */
	protected function criteria() {
		$attrs = array ();
		foreach ( $this->_attrs as $attr => $values ) {
			if (! empty ( $values )) {
				if (count ( $values ) == 1) {
					$attrs [$attr] = $values [0];
				} else {
					$attrs [$attr] ['$in'] = $values;
				}
			}
		}
		return array_merge ( $attrs, $this->_conds );
	}
	/**
	 * 给数据缓冲列添加索引
	 */
	public function addIndex($tableName, $keys, $options = array('background'=>true)) {
		if ($this->_mogoInstance === null) {
			$this->_cache = Yii::app ()->getComponent ( $this->cacheId );
			if (! $this->_cache)
				throw new CException ( Yii::t ( 'yii', 'CCacheHttpSession.cacheID is invalid. Please make sure "{id}" refers to a valid cache application component.', array (
																																												'{id}' => $this->cacheID ) ) );
			$this->_mogoInstance = new DLDMongoD ( $this->mongoOptions ['host'], $this->mongoOptions ['port'], $this->mongoOptions ['database'] );
		}
		return $this->_mogoInstance->ensureIndex ( $keys, $tableName, $options );
	}
	
	/**
	 * 删除索引
	 * @param string $tableName
	 * @param string $keys
	 */
	public function delIndex($tableName, $keys){
		if ($this->_mogoInstance === null) {
			$this->_cache = Yii::app ()->getComponent ( $this->cacheId );
			if (! $this->_cache)
				throw new CException ( Yii::t ( 'yii', 'CCacheHttpSession.cacheID is invalid. Please make sure "{id}" refers to a valid cache application component.', array (
						'{id}' => $this->cacheID ) ) );
			$this->_mogoInstance = new DLDMongoD ( $this->mongoOptions ['host'], $this->mongoOptions ['port'], $this->mongoOptions ['database'] );
		}
		return $this->_mogoInstance->deleteIndex ( $keys, $tableName );
	}
	/**
	 * 往输入缓冲队列中添加一条数据
	 */
	public function insert($tableName, array $data) {
		if ($this->_mogoInstance === null) {
			$this->_cache = Yii::app ()->getComponent ( $this->cacheId );
			if (! $this->_cache)
				throw new CException ( Yii::t ( 'yii', 'CCacheHttpSession.cacheID is invalid. Please make sure "{id}" refers to a valid cache application component.', array (
																																												'{id}' => $this->cacheID ) ) );
			$this->_mogoInstance = new DLDMongoD ( $this->mongoOptions ['host'], $this->mongoOptions ['port'], $this->mongoOptions ['database'] );
		}
		$data ['dld_timestamp'] = $_SERVER ['REQUEST_TIME'];
		$cacheKey = hash ( 'md5', $tableName );
		$datas = $this->_cache->get ( $cacheKey );
		if (! $datas) {
			$datas = array ();
		}
		if (is_array ( $datas ) && count ( $datas ) && (count ( $datas ) >= $this->blockSize || $datas [count ( $datas ) - 1] ['dld_timestamp'] + $this->flushTime <= $_SERVER ['REQUEST_TIME'])) {
			$this->flush ( $tableName );
			$this->_cache->set ( $cacheKey, array(0=>$data) );
			return true;
		} else {
			$datas [] = $data;
		}
		$this->_cache->set ( $cacheKey, $datas );
		return true;
	}
	/**
	 * 强制更新数据缓冲到mongodb中去
	 */
	public function flush($tableName) {
		if ($this->_mogoInstance === null) {
			$this->_cache = Yii::app ()->getComponent ( $this->cacheId );
			if (! $this->_cache)
				throw new CException ( Yii::t ( 'yii', 'CCacheHttpSession.cacheID is invalid. Please make sure "{id}" refers to a valid cache application component.', array (
																																												'{id}' => $this->cacheID ) ) );
			$this->_mogoInstance = new DLDMongoD ( $this->mongoOptions ['host'], $this->mongoOptions ['port'], $this->mongoOptions ['database'] );
		}
		$indexsArray = $this->_mogoInstance->getIndexInfo ( $tableName );
		if (is_array ( $indexsArray ) && count ( $indexsArray )) {
			$this->_mogoInstance->deleteIndexes ( $tableName );
		}
		$cacheKey = hash ( 'md5', $tableName );
		$datas = $this->_cache->get ( $cacheKey );
		if (is_array ( $datas )) {
			if ($this->_mogoInstance->batchInsert ( $datas, $tableName )) {
				$datas = $this->_cache->set ( $cacheKey, false );
			}
		}
		if (is_array ( $indexsArray ) && count ( $indexsArray )) {
			foreach ( $indexsArray as $val ) {
				if (isset ( $val ['_id'] )) {
					unset ( $val ['_id'] );
				}
				unset ( $val ['ns'] );
				$key = $val ['key'];
				unset ( $val ['key'] );
				$val ['background'] = true;
				$this->_mogoInstance->ensureIndex ( $key, $tableName, $val );
			}
		}
	}
	/**
	 * 批量更新数据
	 */
	public function update($tableName, $data, $options = array("multiple"=>true)) {
		if ($this->_mogoInstance === null) {
			$this->_cache = Yii::app ()->getComponent ( $this->cacheId );
			if (! $this->_cache)
				throw new CException ( Yii::t ( 'yii', 'CCacheHttpSession.cacheID is invalid. Please make sure "{id}" refers to a valid cache application component.', array (
																																												'{id}' => $this->cacheID ) ) );
			$this->_mogoInstance = new DLDMongoD ( $this->mongoOptions ['host'], $this->mongoOptions ['port'], $this->mongoOptions ['database'] );
		}
		$this->flush ( $tableName );
		$result = $this->_mogoInstance->update ( $this->criteria (), $data, $tableName, $options );
		$this->clearCondition ();
		return $result;
	}
	/**
	 * 批量删除数据
	 */
	public function remove($tableName) {
		if ($this->_mogoInstance === null) {
			$this->_cache = Yii::app ()->getComponent ( $this->cacheId );
			if (! $this->_cache)
				throw new CException ( Yii::t ( 'yii', 'CCacheHttpSession.cacheID is invalid. Please make sure "{id}" refers to a valid cache application component.', array (
																																												'{id}' => $this->cacheID ) ) );
			$this->_mogoInstance = new DLDMongoD ( $this->mongoOptions ['host'], $this->mongoOptions ['port'], $this->mongoOptions ['database'] );
		}
		$this->flush ( $tableName );
		$result = $this->_mogoInstance->remove ( $this->criteria (), $tableName );
		$this->clearCondition ();
		return $result;
	}
	
	/**
	 * 获得指定查询得记录条数*
	 */
	public function count($collection) {
		try {
			if ($this->_mogoInstance === null) {
				$this->_cache = Yii::app ()->getComponent ( $this->cacheId );
				if (! $this->_cache)
					throw new CException ( Yii::t ( 'yii', 'CCacheHttpSession.cacheID is invalid. Please make sure "{id}" refers to a valid cache application component.', array (
																																													'{id}' => $this->cacheID ) ) );
				$this->_mogoInstance = new DLDMongoD ( $this->mongoOptions ['host'], $this->mongoOptions ['port'], $this->mongoOptions ['database'] );
			}
			$query = array ();
			$result = $this->_mogoInstance->count ( $this->criteria (), $collection );
			$this->clearCondition ();
			return $result;
		} catch ( Exception $ex ) {
			throw $ex;
			return 0;
		}
	}
	/**
	 * 清除查询条件
	 */
	protected function clearCondition() {
		$this->_conds = $this->_attrs = array ();
	}
}